;; ---
;; 1.7

(define (rq-iter tentativa x)
  (if (muito-bom? tentativa x)
      tentativa
      (rq-iter (melhora tentativa x)
                 x)))

(define (melhora tentativa x)
  (media tentativa (/ x tentativa)))

(define (media x y)
  (/ (+ x y) 2))

(define (muito-bom? tentativa x)
  (< (abs (- (quadrado tentativa) x)) precisao))

(define (quadrado x) (* x x))

(define (raizquadrada x)
  (rq-iter 1.0 x))

(define precisao 0.0000000001)
(raizquadrada 900000000000000000000000000) ;; 30000000000000.0
(raizquadrada 90000000000000000000000000000) ;; 3e+14
(raizquadrada 900000010000000000000000000) ;; 30000000166666.664
(raizquadrada 900000000000000010000000000) ;; 30000000000000.0

; (raizquadrada 900000000001000000000000000) ;; Loop infinito!

; (raizquadrada 900000000001000000000000000) ;; Infinito! 

;; Com o 1 em qualquer posicao intermediaria entre os dois ultimos exemplos
;; o resultado será um loop infinito

;; (raizquadrada 900000000010000000000000000) ;; 30000000166666.664
;;(raizquadrada 90000000000000000000000000000) ;; 3e+14

;; Agora vejamos para numeros muito pequenos

(define precisao 0.001)
(raizquadrada 2) ; 1.4142156862745097
(raizquadrada 0.02) ; 0.1444238094866232
(raizquadrada 0.0002) ; 0.03335281609280434, perdeu a precisao

(define precisao 0.00000000001)
(raizquadrada 0.0002) ; 0.014142135623738401, ok de novo

;; O problema deste algoritmo é que para numeros muito grandes a precisao pode ser impossivel de ser atingida,
;; causando um loop infinito. Para números muito pequenos, a precisao pode ser insuficiente. É necessário que
;; a precisao seja calculada dinamicamente. 
;;
;; Para resolver isso, é necessário que a precisão seja algo relativo a x. A seguinte redefinição melhora o problema

; Apenas adiciona o parametro x à precisao
(define (muito-bom? tentativa x)
  (< (abs (- (quadrado tentativa) x)) (precisao x)))

(define (precisao x)
  (/ x 1000000))


